package com.df.gateway.predicate;

import com.df.gateway.handler.GatewayTcpHanlder;
import com.df.library.net.condition.IProtocolPredicate;
import com.df.library.net.handler.ProtocolSelectHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.springframework.util.StringUtils;

public class GatewayTcpPredicate implements IProtocolPredicate {


    @Override
    public boolean check(ChannelHandlerContext ctx, ByteBuf msg) {
        int len = msg.readableBytes();
        if(len<4){
            return false;
        }
        msg.markReaderIndex();
        short moshu = msg.readShort();
        msg.resetReaderIndex();
        String moshuStr = "";
        try {
            moshuStr = String.format("%02x", moshu);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }

        //判断魔术
        if(moshuStr.equals("fafa")){
            return true;
        }
        return false;
    }

    @Override
    public void channelInit(ChannelHandlerContext ctx) {
        ctx.pipeline().remove(ProtocolSelectHandler.class);
        //协议格式
        //4字节表示长度  服务+功能模块+业务方法
        //魔术可以设置变动规则，客户端和服务器按一样的规则在规则时间一起变动即可，防止作弊
        //协议格式： 魔术(2字节，模仿Java魔术，我们起个fafa)|长度(4字节)|服务id(2字节)|功能id(2字节)|业务方法id(2字节)|消息体
        ctx.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
        ctx.pipeline().addLast(new LengthFieldBasedFrameDecoder(8*1024*1024,2,4));
        //自定义协议
        ctx.pipeline().addLast(new GatewayTcpHanlder());
        //channel的生命周期如下：
        //handlerAdded()--->  channelRegistered()--->  channelActive()   ---> channelRead()
        //                                                                        |
        //                                                                        v
        //handlerRemoved()<---channelUnregistered()<---channelInactive()<---channelReadComplete()
        //1.handlerAdded() 当检测到新连接之后，调用 ch.pipeline().addLast(new XXXHandler()); 之后的回调
        //2.channelRegistered() 当前的 channel 的所有的逻辑处理已经和某个 NIO 线程建立了绑定关系
        //3.channelActive() channel 的 pipeline 中已经添加完所有的 handler，并且绑定好一个 NIO 线程之后，这条连接算是真正激活了，接下来就会回调到此方法。
        //4.channelRead() 收到发来的数据，如果数据很长，一个buffer装不下，则此方法会调用多次
        //5.channelReadComplete() 数据读取完毕回调此方法
        //6.channelInactive()  表示这条连接已经被关闭了，这条连接在 TCP 层面已经不再是 ESTABLISH 状态了
        //7.channelUnregistered()  表示与这条连接对应的 NIO 线程移除掉对这条连接的处理
        //8.handlerRemoved() 这条连接上添加的所有的业务逻辑处理器都被移除掉后调用
        //这两个事件已经被触发过了（channel最初只有ProtocolSelectHandler，连接建立后，registered和active已经被触发后，channel最初只有ProtocolSelectHandler
        // 的read0方法也已被触发了），因此在read0里添加的handler，只会触发handlerAdded，registered和active不会触发了，需要手动触发
        ctx.pipeline().fireChannelRegistered();
        ctx.pipeline().fireChannelActive();

    }



}
